package cate.game.activity.limitshop;

import cate.common.table.activity.base.ShopActivityBaseRow;
import cate.common.table.activity.newlimitshop.daily_base.NewLimitShopDailyBaseRow;
import cate.common.table.activity.newlimitshop.daily_item.NewLimitShopDailyItemRow;
import cate.common.table.d.GDOperation;
import cate.common.table.pay.PayItemRow;
import cate.common.util.GameResult;
import cate.game.activity.limitshop.msg.LimitShopDailyNewInfoResp;
import cate.game.res.MixRes;
import cate.game.res.MixResAdder;
import cate.game.role.Role;
import com.fasterxml.jackson.annotation.JsonIgnore;
import easy.java.dev.note.NoteField;
import easy.java.practice.errorcode.EcResult;
import lombok.extern.slf4j.Slf4j;

import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

@Slf4j
public class DailyNewLimitShopActivity extends LimitShopActivity {
    @NoteField("重置天数")
    public int resetDay;
    @NoteField("额外奖励领取状态")
    public Map<Integer, Boolean> extraGot;

    @Override
    public void initialize(Role role) {
        super.initialize(role);
        if (extraGot == null) {
            extraGot = new HashMap<>();
        }
        if (resetDay == 0) {
            resetDay = 1;
        }
    }

    @Override
    public void excelCheck() {
        super.excelCheck();
        List<NewLimitShopDailyBaseRow> configs = getBaseConfigs();
        Map<Integer, NewLimitShopDailyBaseRow> extras = configs.stream().filter(NewLimitShopDailyBaseRow::extraExists)
                .collect(Collectors.toMap(r -> r.id, r -> r));
        extraGot.entrySet().removeIf(entry -> !extras.containsKey(entry.getKey()));
        extras.keySet().stream().filter(k -> !extraGot.containsKey(k)).forEach(k -> extraGot.put(k, false));
    }

    @Override
    public void onDaySpan(boolean silence) {
        super.onDaySpan(silence);
        List<NewLimitShopDailyBaseRow> configs = getBaseConfigs();
        if (configs == null) {
            return;
        }
        int day = getCurrentDay();
        for (NewLimitShopDailyBaseRow config : configs) {
            if (config.resetType == 1) {
                // 每日重置
                reset(config);
            } else if (config.resetType == 2) {
                // 每周重置以7天为单位
                if (day % 7 == 1) {
                    reset(config);
                }
            } else if (config.resetType == 3) {
                // 每月重置以30天为单位
                if (day % 30 == 1) {
                    reset(config);
                }
            }
            if (config.resetType == 1) {
                // 每日重置
                reset(config);
            } else if (config.resetType == 2) {
                // 每周重置以7天为单位
                if (day - resetDay >= 7) {
                    reset(config);
                    resetDay = ((day - 1) / 7) * 7 + 1;
                }
            } else if (config.resetType == 3) {
                // 每月重置以30天为单位
                if (day -resetDay >= 30) {
                    reset(config);
                    resetDay = ((day - 1) / 30) * 30 + 1;
                }
            }
        }
        if (!silence) {
            noticeUpdate();
        }
    }

    /**
     * 重置数据
     *
     * @param config 基础配置
     */
    private void reset(NewLimitShopDailyBaseRow config) {
        buyRecords.entrySet().stream()
                .filter(entry -> getSelfConfig(entry.getKey()) != null && getSelfConfig(entry.getKey()).tag == config.tag)
                .forEach(entry -> entry.setValue(0));
        extraGot.entrySet().forEach(entry -> entry.setValue(false));
    }

    @Override
    public void onWeekSpan(boolean silence) {
        // 周重置改啦
    }

    @Override
    public void onMonthSpan(boolean silence) {
        // 月重置改啦
    }

    @Override
    public void onRoleOpen() {
        super.onRoleOpen();
        resetDay = 1;
        onDaySpan(true);
    }

    @Override
    public void onRoleEnd() {
        super.onRoleEnd();
        extraGot.clear();
        resetDay = 1;
    }

    @Override
    public void noticeUpdate() {
        role.sendNow(new LimitShopDailyNewInfoResp(this));
    }

    /**
     * 获取基础配置列表
     */
    @JsonIgnore
    public List<NewLimitShopDailyBaseRow> getBaseConfigs() {
        return role.getGame().table.limitShopNew.daily_base.getList().stream().filter(row -> row.funcId == funcId() && row.configId == configTid())
                .collect(Collectors.toList());
    }

    /**
     * 根据ID获取基础配置
     */
    @JsonIgnore
    public NewLimitShopDailyBaseRow getBaseConfigByGT(int tid) {
        return role.getGame().table.limitShopNew.daily_base.get(tid);
    }

    /**
     * 根据分组和页签获取基础配置
     *
     * @param group 分组
     * @param tag 页签
     */
    @JsonIgnore
    public NewLimitShopDailyBaseRow getBaseConfigByGT(int group, int tag) {
        return getBaseConfigs().stream()
                .filter(row -> row.group == group && row.tag == tag)
                .findAny().orElse(null);
    }

    @JsonIgnore
    public NewLimitShopDailyItemRow getSelfConfig(int tid) {
        return role.getGame().table.limitShopNew.daily_item.get(tid);
    }

    @Override
    protected ShopActivityBaseRow getConfig(int tid) {
        return getSelfConfig(tid);
    }

    @JsonIgnore
    @Override
    protected Map<Integer, ShopActivityBaseRow> getConfigs() {
        Map<Integer, Integer> tagToGroup = getBaseConfigs().stream().collect(Collectors.toMap(r -> r.tag, r -> r.group));
        return role.getGame().table.limitShopNew.daily_item.getList().stream()
                .filter(row -> tagToGroup.containsKey(row.tag) && tagToGroup.get(row.tag) == row.group)
                .collect(Collectors.toMap(r -> r.id, r -> r));
    }

    @JsonIgnore
    @Override
    protected int getGDOperation() {
        return GDOperation.ACT_DAILY_SHOP_NEW;
    }

    /**
     * 是否能够一键购买
     */
    public GameResult<Void> allowPayOneKey(PayItemRow pir) {
        GameResult<Void> r = new GameResult<>();
        NewLimitShopDailyBaseRow baseConfig = getBaseConfigByGT(pir.funcSubId, Integer.parseInt(pir.funcSubConf));
        if (baseConfig == null || baseConfig.configId != configTid()) {
            return r.fail("无法购买呀");
        }
        if (!baseConfig.extraExists()) {
            return r.fail("没有一键购买呀");
        }
        for (int tid : baseConfig.extraItemCons.keySet()) {
            int num = baseConfig.extraItemCons.get(tid);
            if (!buyRecords.containsKey(tid)) {
                return r.fail("未找到配置1");
            }
            ShopActivityBaseRow config = getConfig(tid);
            if (config == null) {
                return r.fail("未找到配置2");
            }
            if (config.limit != -1) {
                if (buyRecords.get(tid) + num > config.limit) {
                    return r.fail(904818, "无法一键购买");
                }
            }
        }
        return r.success();
    }

    /**
     * 一键购买回调
     */
    public void onPaySuccessOneKey(PayItemRow pir) {
        NewLimitShopDailyBaseRow baseConfig = getBaseConfigByGT(pir.funcSubId, Integer.parseInt(pir.funcSubConf));
        if (baseConfig == null || baseConfig.configId != configTid()) {
            log.error("[DailyNewLimitShopActivity] 无匹配的一键购买配置 {}", pir.id);
            return;
        }
        MixRes overall = new MixRes();
        baseConfig.extraItemCons.forEach((key, value) -> overall.addList(provideReward(key, value, false)));
        role.getGame().notice.dialogReward(role, overall);
        noticeUpdate();
    }

    /**
     * 领取额外奖励
     *
     * @param tid 配置ID
     * @return 领取结果
     */
    public EcResult<DailyNewLimitShopActivity> receiveExtraReward(int tid) {
        EcResult<DailyNewLimitShopActivity> r = new EcResult<>();
        r.data = this;
        NewLimitShopDailyBaseRow baseConfig = getBaseConfigByGT(tid);
        if (baseConfig == null || baseConfig.configId != configTid()) {
            return r.fail("配置不存在");
        }
        if (!baseConfig.extraExists() || !extraGot.containsKey(tid)) {
            return r.fail("无全额购买奖励");
        }
        if (extraGot.get(tid)) {
            return r.fail("无法重复领取");
        }
        for (Map.Entry<Integer, Integer> entry : baseConfig.extraItemCons.entrySet()) {
            if (!buyRecords.containsKey(entry.getKey()) || buyRecords.get(entry.getKey()) < entry.getValue()) {
                return r.fail("不满足领取条件");
            }
        }
        MixRes extraReward = new MixRes(baseConfig.extraRewardStr);
        if (extraReward.isEmpty()) {
            return r.fail("奖励配置错误");
        }
        extraGot.put(tid, true);
        new MixResAdder().setRes(extraReward)
                .setOperation(GDOperation.ACT_DAILY_SHOP_EXTRA)
                .setOperationSub(tid)
                .setDialogReward(true)
                .setSendMailWhenFull(true)
                .exe(role);
        return r.success();
    }
}
